/*
 * DataBean.Java
 
 *  Copyright 2011 David Connell
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.puresilk.android.db;

import org.puresilk.android.util.Util;
import org.puresilk.android.util.Logger;

import android.content.ContentValues;
import android.database.Cursor;

public class DataBean  {
	private static final Logger logger = Logger.getInstance("DataBean");
	private static Db db = null;
	private ContentValues cols = null;
	private String name = null;
	
	private static final String STRING_TYPE = "string";
	
	/**
	 * Factory method for asking for data
	 * beans by resource id.
	 * 
	 * @param res
	 * @param resid
	 * @return
	 */
	public static DataBean createBean(android.content.Context ctx,int resid) {
		
		// create entity context
		DataBean bean = new DataBean(ctx.getResources().getStringArray(resid));
	
		// return the bean
		return bean;
	}

	/**
	 * Factory method for asking for data
	 * beans by name.
	 * 
	 * @param res
	 * @param entity
	 * @return
	 */
	public static DataBean createBean(android.content.Context ctx,String entity) {
		// return bean
		return createBean(ctx, Util.getResourceId(ctx, entity, STRING_TYPE));
	}

	/**
	 * Static method to access standard constructor.
	 * 
	 * @param props
	 * @return
	 */
	public static DataBean createBean(String [] props) {
		return new DataBean(props);
	}
	
	protected Db getDb() {
		if(db == null)
			db = new Db();
		return db;
	}
	
	public DataBean(String [] props){
		cols = new ContentValues();
		Context ctx = new Context(props);
		getDb().setContext(ctx);
		name = props[0];
		cols = ctx.getDefaults();
	}
	
	public ContentValues defaultWhere(){
		ContentValues cv = new ContentValues();
		cv.put("id",(String)cols.get("id"));
	
		return cv;
	}
	
	public String getName() { return name; }
	
	/**
	 * Column value getter
	 * 
	 * @param fld
	 * @param val
	 */
	public void put(String fld, String val){
		cols.put(fld, val);
	}
	
	/**
	 * Update and save. 
	 * 
	 * @param newVals
	 */
	public void update(ContentValues newVals) {
		update(newVals,true);
	}
	
	/**
	 * Update field values with newVals and
	 * optionally call save.
	 * 
	 * @param newVals
	 * @param save
	 */
	public void update(ContentValues newVals, boolean save) {
		// get list of flds names for keys
		String [] flds = db.getContext().getColumnNames();
		for (int i = 0; 1 < flds.length; i++)
			// if there is a new value for this one
			if (newVals.containsKey(flds[i]) )
				// update cols
				cols.put(flds[i],newVals.getAsString(flds[i]));
		
		if(save)
			// save on demand
			save();
	}
	
	/**
	 * Column value setter
	 * 
	 * @param fld
	 * @return
	 */
	public Object get(String fld) {
		return cols.get(fld);
	}
	
	public String [] getFieldNames(){
		return db.getContext().getColumnNames();
	}
	
	/**
	 * Fill up with a query using
	 * the row id.
	 * 
	 * @param id
	 * @return
	 */
	public int fetch(int id) {
		int rv = 1;
		// get full list of column names
		String [] flds = db.getContext().getColumnNames();
		
		// build a where clause
		ContentValues where = new ContentValues();
		where.put("id",id);
		
		// query db for record
		Cursor crsr = db.select(flds, where, null, null, null);
		
		// if found, move to local storage
		if(crsr.moveToFirst()) {
			for(int i = 0; i < flds.length; i++)
				// moves are type dependent
				switch(db.getContext().getColType(flds[i])) {
					case Context.ColMeta.AUTOKEY:
					case Context.ColMeta.INTEGER:
						cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
						break;
					case Context.ColMeta.DATE:
					case Context.ColMeta.TIME:
					case Context.ColMeta.DATETIME:
						cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
						break;
					case Context.ColMeta.FLOAT:
						cols.put(flds[i],crsr.getDouble(crsr.getColumnIndex(flds[i])));
						break;
					default: 
						cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
				}
		}
		else
			// didn't get anything...
			rv = 0;
		
		return rv;
	}
	
	/**
	 * set from cursor
	 */
	public void setFields(Cursor crsr) {
		String[] flds = crsr.getColumnNames();
		logger.debug("Flds = >" + flds.toString());
		for(int i=0;i<flds.length;i++) {
			switch(db.getContext().getColType(flds[i])) {
				case Context.ColMeta.AUTOKEY:
				case Context.ColMeta.INTEGER:
					cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
					break;
				case Context.ColMeta.DATE:
				case Context.ColMeta.TIME:
				case Context.ColMeta.DATETIME:
					cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
					break;
				case Context.ColMeta.FLOAT:
					cols.put(flds[i],crsr.getDouble(crsr.getColumnIndex(flds[i])));
					break;
				default: 
					cols.put(flds[i],crsr.getString(crsr.getColumnIndex(flds[i])));
		
			}
		}
	}
	
	/**
	 * Fetch all rows that match the filter
	 */
	public Cursor select(ContentValues fltr) {
		return db.select(null,fltr,null,null,null);
	}
	
	/**
	 * Save bean to db
	 */
	public void save() {
		if(cols.getAsInteger("id") == 0)
			// insert
			db.insert(cols);
		else
			// update
			db.update(cols, getIdWhere(cols.getAsInteger("id").intValue()));
	}
		
	/** 
	 * Remote bean from db
	 */
	public void remove(){
		db.delete( getIdWhere(cols.getAsInteger("id").intValue()));
	}

	/**
	 * Return ContentValues to build where clause.
	 * 
	 * @param id
	 * @return
	 */
	private ContentValues getIdWhere(int id){
		ContentValues where = new ContentValues();
		where.put("id",id);
		return where;
	}
}
